package com.maltys.backtracking;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author malty
 * @link <a href="https://leetcode.cn/problems/path_sum/">n皇后问题</a>
 */
public class NQueens {
    public static void main(String[] args) {
        NQueens nQueens = new NQueens();
        List<List<String>> lists = nQueens.solveNQueens(10);
        lists.forEach(System.out::println);
        System.out.println(lists.size());
    }

    public List<List<String>> solveNQueens(int n) {
        char[][] queens = new char[n][n];
        for (char[] queen : queens) {
            Arrays.fill(queen, '.');
        }

        List<List<String>> res = new ArrayList<>();
        backTracing(queens, 0, new ArrayList<>(), res);
        return res;
    }

    private void backTracing(char[][] queens, int row, List<String> list, List<List<String>> res) {
        if (list.size() == queens.length) {
            res.add(new ArrayList<>(list));
            return;
        }

        for (int i = row; i < queens.length; i++) {
            for (int j = 0; j < queens.length; j++) {
                if (queens[i][j] == '.' && isValid(queens, i, j)) {
                    queens[i][j] = 'Q';
                    list.add(new String(queens[i]));
                    backTracing(queens, i + 1, list, res);
                    list.remove(list.size() - 1);
                    queens[i][j] = '.';
                }
            }
        }
    }

    private boolean isValid(char[][] queens, int row, int col) {
        for (int i = 0; i < row; i++) {
            if (queens[i][col] == 'Q') {
                return false;
            }
        }

        // 检查左上对角线
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
            if (queens[i][j] == 'Q') {
                return false;
            }
        }

        // 检查右上对角线
        for (int i = row - 1, j = col + 1; i >= 0 && j < queens.length; i--, j++) {
            if (queens[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }
}
